/*-------------------------------------------------------------------------
 *
 * instrument.h
 *	  运行时统计收集的定义
 *
 *
 * Copyright (c) 2001-2022, PostgreSQL Global Development Group
 *
 * src/include/executor/instrument.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef INSTRUMENT_H
#define INSTRUMENT_H

#include "portability/instr_time.h"


/*
 * BufferUsage和WalUsage计数器不断增加，
 * 即，绝不能重置为零，以便我们能够计算在任意时间段内
 * 计数器增加了多少。
 */
typedef struct BufferUsage
{
	int64		shared_blks_hit;	/* 共享缓冲区命中次数 */
	int64		shared_blks_read;	/* 读取的共享磁盘块数 */
	int64		shared_blks_dirtied;	/* 脏污的共享块数量 */
	int64		shared_blks_written;	/* 写入的共享磁盘块数 */
	int64		local_blks_hit; /* 本地缓冲区命中次数 */
	int64		local_blks_read;	/* 读取的本地磁盘块数 */
	int64		local_blks_dirtied; /* 脏污的本地块数量 */
	int64		local_blks_written; /* 写入的本地磁盘块数 */
	int64		temp_blks_read; /* 读取的临时块数 */
	int64		temp_blks_written;	/* 写入的临时块数 */
	instr_time	blk_read_time;	/* 读取块花费的时间 */
	instr_time	blk_write_time; /* 写入块花费的时间 */
	instr_time	temp_blk_read_time; /* 读取临时块花费的时间 */
	instr_time	temp_blk_write_time;	/* 写入临时块花费的时间 */
} BufferUsage;

/*
 * WalUsage只跟踪WAL活动，如WAL记录生成，
 * 可按查询测量，并通过EXPLAIN命令、
 * pg_stat_statements扩展等显示。它不跟踪其他WAL活动，
 * 如不值得按查询测量的WAL写入。取而代之的是，
 * 由WalStats中的WAL全局统计计数器跟踪。
 */
typedef struct WalUsage
{
	int64		wal_records;	/* 产生的WAL记录数量 */
	int64		wal_fpi;		/* 产生的WAL完整页面图像数量 */
	uint64		wal_bytes;		/* 产生的WAL记录大小 */
} WalUsage;

/* 包含在InstrAlloc的instrument_options位掩码中的标志位 */
typedef enum InstrumentOption
{
	INSTRUMENT_TIMER = 1 << 0,	/* 需要计时器（和行计数） */
	INSTRUMENT_BUFFERS = 1 << 1,	/* 需要缓冲区使用情况 */
	INSTRUMENT_ROWS = 1 << 2,	/* 需要行计数 */
	INSTRUMENT_WAL = 1 << 3,	/* 需要WAL使用情况 */
	INSTRUMENT_ALL = PG_INT32_MAX
} InstrumentOption;

typedef struct Instrumentation
{
	/* 在节点创建时设置的参数： */
	bool		need_timer;		/* 如果需要计时器数据，则为真 */
	bool		need_bufusage;	/* 如果我们需要缓冲区使用数据，则为真 */
	bool		need_walusage;	/* 如果我们需要WAL使用数据，则为真 */
	bool		async_mode;		/* 如果节点处于异步模式，则为真 */
	/* 当前计划周期的信息： */
	bool		running;		/* 如果我们已完成第一元组，则为真 */
	instr_time	starttime;		/* 当前节点迭代的开始时间 */
	instr_time	counter;		/* 此节点的累计运行时间 */
	double		firsttuple;		/* 此周期的第一元组时间 */
	double		tuplecount;		/* 此循环中已发出的元组数量 */
	BufferUsage bufusage_start; /* 开始时的缓冲区使用情况 */
	WalUsage	walusage_start; /* 开始时的WAL使用情况 */
	/* 所有已完成周期的累计统计信息： */
	double		startup;		/* 总启动时间（以秒为单位） */
	double		total;			/* 总时间（以秒为单位） */
	double		ntuples;		/* 产生的总元组数 */
	double		ntuples2;		/* 特定于节点的次要元组计数器 */
	double		nloops;			/* 此节点的运行周期数 */
	double		nfiltered1;		/* 被scanqual或joinqual移除的元组数 */
	double		nfiltered2;		/* 被“其他”资格移除的元组数 */
	BufferUsage bufusage;		/* 总缓冲区使用情况 */
	WalUsage	walusage;		/* 总WAL使用情况 */
} Instrumentation;

typedef struct WorkerInstrumentation
{
	int			num_workers;	/* 后续结构的数量 */
	Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER];
} WorkerInstrumentation;

extern PGDLLIMPORT BufferUsage pgBufferUsage;
extern PGDLLIMPORT WalUsage pgWalUsage;

extern Instrumentation *InstrAlloc(int n, int instrument_options,
								   bool async_mode);
extern void InstrInit(Instrumentation *instr, int instrument_options);
extern void InstrStartNode(Instrumentation *instr);
extern void InstrStopNode(Instrumentation *instr, double nTuples);
extern void InstrUpdateTupleCount(Instrumentation *instr, double nTuples);
extern void InstrEndLoop(Instrumentation *instr);
extern void InstrAggNode(Instrumentation *dst, Instrumentation *add);
extern void InstrStartParallelQuery(void);
extern void InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage);
extern void InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage);
extern void BufferUsageAccumDiff(BufferUsage *dst,
								 const BufferUsage *add, const BufferUsage *sub);
extern void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add,
							  const WalUsage *sub);

#endif							/* INSTRUMENT_H */
